home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1996
/
MacHack 1996.toast
/
Hacks
/
Hacks ’87
/
Source ƒ.sit
/
Source ƒ
/
C ƒ
/
TRANS-LSC
/
TransDisplay.c
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
Shift JIS
UTF-8
Wrap
Text File
|
1986-11-12
|
23.9 KB
|
1,105 lines
|
[
TEXT/KAHL
]
/*
TransDisplay version 1.0 - TransSkel plug-in module supporting
an arbitrary number of generic display windows with memory.
TransSkel and TransDisplay are public domain, and are written by:
Paul DuBois
Wisconsin Regional Primate Research Center
1220 Capital Court
Madison WI 53706 USA
UUCP: {allegra,ihnp4,seismo}!uwvax!uwmacc!dubois
ARPA: dubois@unix.macc.wisc.edu
dubois@rhesus.primate.wisc.edu
This version of TransDisplay written for LightspeedC. LightspeedC
is a trademark of:
THINK Technologies, Inc
420 Bedford Street Suite 350
Lexington, MA 02173 USA
History
08/25/86 Genesis. Beta version.
09/15/86 Changed to allow arbitrary number of windows. Changed
version number to 1.0.
*/
/*
The following symbol controls the compile mode. If it is #define'd,
TransDisplay allows only a single display window, and generates
less code. If it is #undef'ed, TransDisplay allows an arbitrary
number of display windows, but generates more code.
*/
# undef singleDisplay
# include <ControlMgr.h> /* includes WindowMgr.h, QuickDraw.h, MacTypes.h */
# include <TextEdit.h>
# include "TransDisplay.h"
/*
Display window types, constants, variables.
*/
# define monaco 4
/*
Default values for display window characteristics
*/
static int d_font = monaco; /* default font */
static int d_size = 9; /* default pointsize */
static int d_wrap = 0; /* default word wrap (on) */
static int d_just = teJustLeft; /* default justification */
static long d_maxText = 30000L; /* default max text allowed */
static long d_flushAmt = 25000L; /* default autoflush amount */
static ProcPtr d_activate = nil; /* default notification proc */
/*
Lowest allowable values for autoflush characteristics
*/
# define d_loMaxText (100L)
# define d_loFlushAmt (100L)
# ifndef singleDisplay
/*
New(TypeName) returns handle to new object, for any TypeName.
If there is insufficient memory, the result is nil.
*/
# define New(x) (x **) NewHandle ((Size) sizeof (x))
/*
dwList points to a list of structures describing the known display
windows.
curDispWind is the current output window.
If curDispWind = nil, output is currently turned off.
*/
typedef struct DisplayInfo
{
WindowPtr dWind; /* display window */
TEHandle dTE; /* window text */
ControlHandle dScroll; /* window scroll bar */
ProcPtr dActivate; /* notification procedure */
long dMaxText; /* max text length */
long dFlushAmt; /* amount to autoflush */
struct DisplayInfo **dNext; /* next window structure */
} DisplayInfo, *DIPtr, **DIHandle;
static DIHandle dwList = nil;
# endif
/*
Variables pertaining to the display window being operated on
(updated, resized, etc.). This window is not necessarily the
same as curDispWind! These variables are synced to the window
with SyncGlobals.
*/
# ifndef singleDisplay
static DIHandle dispInfo; /* info structure */
# endif
static WindowPtr dispWind = nil; /* the window */
static TEHandle dispTE; /* window text */
static ControlHandle dispScroll; /* the scroll bar */
static ProcPtr dActivate; /* notification procedure */
static long dMaxText; /* max text allowed */
static long dFlushAmt; /* amount to flush */
/*
curDispWind is the current output window.
If curDispWind = nil, output is turned off.
*/
static WindowPtr curDispWind = nil;
/* -------------------------------------------------------------------- */
/* Miscellaneous Internal (private) Routines */
/* -------------------------------------------------------------------- */
/*
Draw grow box of dispWind in lower right hand corner
*/
static DrawGrowBox ()
{
register RgnHandle oldClip;
Rect r;
r = dispWind->portRect;
r.left = r.right - 15; /* draw only in corner */
r.top = r.bottom - 15;
oldClip = NewRgn ();
GetClip (oldClip);
ClipRect (&r);
DrawGrowIcon (dispWind);
SetClip (oldClip);
DisposeRgn (oldClip);
}
/* -------------------------------------------------------------------- */
/* Lowest-level Internal (Private) Display Window Routines */
/* -------------------------------------------------------------------- */
# ifndef singleDisplay
/*
Get display window info associated with window.
Return nil if window isn't a known display window.
*/
static DIHandle GetDInfo (theWind)
WindowPtr theWind;
{
register DIHandle h;
for (h = dwList; h != nil; h = (**h).dNext)
{
if ((**h).dWind == theWind)
return (h);
}
return (nil);
}
# endif
# ifdef singleDisplay
# define SyncGlobals(x) ; /* make it a nop */
# else
/*
Synchronize globals to a display window. theWind must be a legal
display window, with one exception: if theWind is nil, the
variables are synced to the current port. That is safe (and
correct) because:
(i) nil is only passed by display window handler procedures,
which are only called by TransSkel for display window
events.
(ii) TransSkel always sets the port to the window before
calling the handler proc.
Hence, use of the current port under these circumstances
always produces a legal display window.
SyncGlobals is not used in single display mode, because the
globals are all set by SetupDWindow and do not change thereafter.
*/
static SyncGlobals (theWind)
WindowPtr theWind;
{
register DIPtr dp;
if (theWind == nil) /* use current window */
GetPort (&theWind);
dispWind = theWind;
dispInfo = GetDInfo (dispWind);
dp = *dispInfo;
dispScroll = (*dp).dScroll;
dispTE = (*dp).dTE;
dActivate = (*dp).dActivate;
dMaxText = (*dp).dMaxText;
dFlushAmt = (*dp).dFlushAmt;
}
# endif
/*
Calculate the dimensions of the editing rectangle for
dispWind (which must be set properly and is assumed to be
the current port). (The viewRect and destRect are the
same size.) Assumes the port, text font and text size are all
set properly. The viewRect is sized so that an integral
number of lines can be displayed in it, i.e., so that a
partial line never shows at the bottom.
*/
static CalcEditRect (r)
Rect *r;
{
FontInfo f;
register int lineHeight;
GetFontInfo (&f);
lineHeight = f.ascent + f.descent + f.leading;
*r = dispWind->portRect;
r->left += 4;
r->right -= 17; /* leave room for scroll bar + 2 */
r->top += 2;
r->bottom = r->top + ((r->bottom - r->top - 2) / lineHeight) * lineHeight;
}
/*
Calculate the dimensions of the scroll bar rectangle for the
window. Make sure that the edges overlap the window frame and
the grow box.
*/
static CalcScrollRect (r)
Rect *r;
{
*r = dispWind->portRect;
++r->right;
--r->top;
r->left = r->right - 16;
r->bottom -= 14;
}
/*
Calculate the number of lines currently scrolled off
the top.
*/
static LinesOffTop ()
{
register TEPtr ePtr;
ePtr = *dispTE;
return (((*ePtr).viewRect.top - (*ePtr).destRect.top)
/ (*ePtr).lineHeight);
}
/*
Highlight the scroll bar properly. This means that it's not
made active if the window itself isn't active, even if
there's enough text to fill the window.
*/
static HiliteScroll ()
{
HiliteControl (dispScroll, dispWind == FrontWindow () &&
GetCtlMax (dispScroll) > 0 ? 0 : 255);
}
/*
Scroll to the correct position. lDelta is the
amount to CHANGE the current scroll setting by.
Positive scrolls the text up, negative down.
*/
static ScrollText (lDelta)
int lDelta;
{
register int lHeight;
register int newLine;
register int topLine;
lHeight = (**dispTE).lineHeight;
topLine = LinesOffTop ();
newLine = topLine + lDelta;
if (newLine < 0)
newLine = 0;
if (newLine > GetCtlMax (dispScroll))
newLine = GetCtlMax (dispScroll);
SetCtlValue (dispScroll, newLine);
TEScroll (0, (topLine - newLine ) * lHeight, dispTE);
}
/*
Filter proc for tracking mousedown in scroll bar. The code for
the part originally hit is stored in the control's reference
value by Mouse () before calling this.
Scroll by one line if the mouse is in an arrow. Scroll by a half
window's worth of lines if the mouse is in a page region.
*/
static pascal void TrackScroll (theScroll, partCode)
ControlHandle theScroll;
int partCode;
{
register int lDelta;
register int halfPage;
if (partCode == GetCRefCon (theScroll)) /* still in same part? */
{
halfPage = (((**dispTE).viewRect.bottom - (**dispTE).viewRect.top)
/ (**dispTE).lineHeight) / 2;
if (halfPage == 0)
++halfPage;
switch (partCode)
{
case inUpButton: lDelta = -1; break;
case inDownButton: lDelta = 1; break;
case inPageUp: lDelta = -halfPage; break;
case inPageDown: lDelta = halfPage; break;
}
ScrollText (lDelta);
}
}
/*
Adjust the text in the text record and the scroll bar. This is
called for major catastrophes, such as resizing the window, or
changing the word wrap style. It makes sure the view and
destination rectangles are sized properly, and that the bottom
line of text never scrolls up past the bottom line of the
window, if there's enough to fill the window, and that the
scroll bar max and current values are set properly.
Resizing the dest rect just means resetting the right edge
(the top is NOT reset), since text might be scrolled off the
top (i.e., destRect.top != 0).
*/
static OverhaulDisplay ()
{
Rect r;
register int nLines; /* number of lines in TERec */
register int visLines; /* number of lines displayable in window */
register int topLines; /* number of lines currently scrolled off top */
register int scrollLines; /* number of lines to scroll down */
register int lHeight;
CalcEditRect (&r);
(**dispTE).destRect.right = r.right;
(**dispTE).viewRect = r;
TECalText (dispTE); /* recalc line starts */
/*r = (**dispTE).viewRect;*/ /* ?? */
lHeight = (**dispTE).lineHeight;
nLines = (**dispTE).nLines;
visLines = (r.bottom - r.top) / lHeight;
topLines = LinesOffTop ();
/*
If the text doesn't fill the window (visLines > nLines - topLines),
pull the text down if possible (if topLines > 0). Make sure not
to try to scroll down by more lines than are hidden off the top.
*/
scrollLines = visLines - (nLines - topLines);
if (scrollLines > 0 && topLines > 0)
{
if (scrollLines > topLines)
scrollLines = topLines;
TEScroll (0, scrollLines * lHeight, dispTE);
topLines -= scrollLines;
}
TEUpdate (&r, dispTE);
SetCtlMax (dispScroll, nLines - visLines < 0 ? 0 : nLines - visLines);
SetCtlValue (dispScroll, topLines);
HiliteScroll ();
}
/* ---------------------------------------------------------------- */
/* Window Handler Routines */
/* ---------------------------------------------------------------- */
/*
When the window comes active, highlight the scroll bar appropriately.
When the window is deactivated, un-highlight the scroll bar.
Redraw the grow box.
Notify the host as appropriate.
Note that clicking close box hides the window, which generates a
deactivate event, so there is no need for a close notifier.
*/
static Activate (isActive)
Boolean isActive;
{
SyncGlobals (nil); /* sync to current port */
DrawGrowBox ();
HiliteScroll ();
if (dActivate != nil)
(*dActivate) (isActive);
}
/*
Update window. The update event might be in response to a
window resizing. If so, move and resize the scroll bar,
and recalculate the text display.
The ValidRect call is done because the HideControl adds the
control bounds box to the update region - which would generate
another update event! Since everything is redrawn below anyway,
the ValidRect is used to cancel the update.
*/
static Update (resized)
Boolean resized;
{
Rect r;
SyncGlobals (nil); /* sync to current port */
r = dispWind->portRect;
EraseRect (&r);
if (resized)
{
HideControl (dispScroll);
r = (**dispScroll).contrlRect;
ValidRect (&r);
CalcScrollRect (&r);
SizeControl (dispScroll, 16, r.bottom - r.top);
MoveControl (dispScroll, r.left, r.top);
OverhaulDisplay ();
ShowControl (dispScroll);
}
else
{
r = (**dispTE).viewRect;
TEUpdate (&r, dispTE); /* redraw text display */
}
DrawGrowBox ();
DrawControls (dispWind); /* redraw scroll bar */
}
/*
Handle mouse clicks in window
*/
static Mouse (thePt, t, mods)
Point thePt;
long t;
int mods;
{
register int thePart;
register int oldCtlValue;
SyncGlobals (nil); /* sync to current port */
if ((thePart = TestControl (dispScroll, thePt)) == inThumb)
{
oldCtlValue = GetCtlValue (dispScroll);
if (TrackControl (dispScroll, thePt, nil) == inThumb)
ScrollText (GetCtlValue (dispScroll) - oldCtlValue);
}
else if (thePart != 0)
{
SetCRefCon (dispScroll, (long) thePart);
(void) TrackControl (dispScroll, thePt, &TrackScroll);
}
}
/*
Remove the display window from the list, and dispose of it.
Since the clobber procedure is never called except for real display
windows, and since the list must therefore be non-empty, it is
not necessary to check the legality of the window or that the
window's in the list.
Must do SetDWindow (nil) to turn output off, if the window being
clobbered is the current output window.
*/
static Clobber ()
{
# ifndef singleDisplay
register DIHandle h, h2;
# endif
SyncGlobals (nil); /* sync to current port */
if (dispWind == curDispWind)
SetDWindow (nil);
# ifndef singleDisplay
if ((**dwList).dWind == dispWind) /* is it the first window in list? */
{
h2 = dwList;
dwList = (**dwList).dNext;
}
else
{
for (h = dwList; h != nil; h = h2)
{
h2 = (**h).dNext;
if ((**h2).dWind == dispWind) /* found it */
{
(**h).dNext = (**h2).dNext;
break;
}
}
}
DisposHandle (h2); /* get rid of information structure */
# endif
TEDispose (dispTE); /* toss text record */
DisposeWindow (dispWind); /* toss window and scroll bar */
dispWind = nil;
}
/* ---------------------------------------------------------------- */
/* Control Routines */
/* ---------------------------------------------------------------- */
/*
Test whether a window is a legal display window or not
*/
Boolean IsDWindow (theWind)
WindowPtr theWind;
{
# ifdef singleDisplay
return (theWind == dispWind && dispWind != nil);
# else
return (GetDInfo (theWind) != nil);
# endif
}
/*
Return handle to display window's text record
*/
TEHandle GetDWindowTE (theWind)
WindowPtr theWind;
{
# ifndef singleDisplay
register DIHandle dInfo;
return (GetDInfo (theWind) == nil ? nil : (**dInfo).dTE);
# else
return (IsDWindow (theWind) ? dispTE : nil);
# endif
}
/*
Change the text display characteristics of a display window
and redisplay it. As a side effect, this always scrolls to the
home position.
*/
SetDWindowStyle (theWind, font, size, wrap, just)
WindowPtr theWind;
int font;
int size;
int wrap;
int just;
{
GrafPtr savePort;
FontInfo f;
register TEHandle te;
Rect r;
if (theWind == nil) /* reset window creation defaults */
{
d_font = font;
d_size = size;
d_wrap = wrap;
d_just = just;
return;
}
if (IsDWindow (theWind))
{
GetPort (&savePort);
SyncGlobals (theWind);
SetPort (dispWind);
te = dispTE;
r = (**te).viewRect;
EraseRect (&r);
r = (**te).destRect; /* scroll home without redrawing */
OffsetRect (&r, 0, 2 - r.top);
(**te).destRect = r;
(**te).crOnly = wrap; /* set word wrap */
TESetJust (just, te); /* set justification */
TextFont (font); /* set the font and point size */
TextSize (size); /* of text record (this is the */
GetFontInfo (&f); /* hard part) */
(**te).lineHeight = f.ascent + f.descent + f.leading;
(**te).fontAscent = f.ascent;
(**te).txFont = font;
(**te).txSize = size;
OverhaulDisplay ();
SetPort (savePort);
}
}
/*
Scroll the text in the window so that line lineNum is at the top.
First line is line zero.
*/
SetDWindowPos (theWind, lineNum)
WindowPtr theWind;
int lineNum;
{
GrafPtr savePort;
if (IsDWindow (theWind))
{
GetPort (&savePort);
SyncGlobals (theWind);
SetPort (dispWind);
ScrollText (lineNum - GetCtlValue (dispScroll));
SetPort (savePort);
}
}
/*
Set display window activate notification procedure.
Pass nil to disable it.
*/
SetDWindowNotify (theWind, p)
WindowPtr theWind;
ProcPtr p;
{
# ifndef singleDisplay
register DIHandle dInfo;
# endif
if (theWind == nil) /* reset window creation default */
{
d_activate = p;
return;
}
# ifdef singleDisplay
if (IsDWindow (theWind))
dActivate = p;
# else
if ((dInfo = GetDInfo (theWind)) != nil)
{
(**dInfo).dActivate = p;
}
# endif
}
/*
Set display window autoflush characteristics
*/
SetDWindowFlush (theWind, maxText, flushAmt)
WindowPtr theWind;
long maxText;
long flushAmt;
{
# ifndef singleDisplay
register DIHandle dInfo;
# endif
if (maxText > 32767L)
maxText = 32767L;
if (maxText < d_loMaxText)
maxText = d_loMaxText;
if (flushAmt < d_loFlushAmt)
flushAmt = d_loFlushAmt;
if (theWind == nil) /* reset window creation defaults */
{
d_maxText = maxText;
d_flushAmt = flushAmt;
return;
}
# ifdef singleDisplay
if (IsDWindow (theWind))
{
dMaxText = maxText;
dFlushAmt = flushAmt;
}
# else
if ((dInfo = GetDInfo (theWind)) != nil)
{
(**dInfo).dMaxText = maxText;
(**dInfo).dFlushAmt = flushAmt;
}
# endif
}
/*
Set which display window is to be used for output. If theWind
is nil, output is turned off. If theWind is not a legal display
window, nothing is done.
*/
SetDWindow (theWind)
WindowPtr theWind;
{
if (theWind == nil || IsDWindow (theWind))
{
curDispWind = theWind;
}
}
/*
Get the WindowPtr of the current output display window. If
output is turned off, this will be nil.
*/
GetDWindow (theWind)
WindowPtr *theWind;
{
*theWind = curDispWind;
}
/*
Flush text from the window and readjust the display.
*/
FlushDWindow (theWind, byteCount)
WindowPtr theWind;
long byteCount;
{
if (IsDWindow (theWind))
{
SyncGlobals (theWind);
TESetSelect (0L, byteCount, dispTE); /* select text */
TEDelete (dispTE); /* clobber it */
OverhaulDisplay ();
}
}
/*
Create and initialize a display window and the associated data
structures, and return the window pointer. Install window in
list of display windows.
*/
static SetupDWindow ()
{
Rect r;
GrafPtr savePort;
# ifndef singleDisplay
register DIHandle dInfo;
# endif
GetPort (&savePort);
SkelWindow (dispWind, /* the window */
Mouse, /* mouse click handler */
nil, /* key clicks are ignored */
Update, /* window updating procedure */
Activate, /* window activate/deactivate procedure */
nil, /* TransSkel hides window if no close proc */
/* (generates deactivate event) */
Clobber, /* window disposal procedure */
nil, /* no idle proc */
false); /* irrelevant since no idle proc */
/*
Build the scroll bar. Make sure the borders overlap the
window frame and the frame of the grow box.
*/
CalcScrollRect (&r);
dispScroll = NewControl (dispWind, &r, "\p", true, 0, 0, 0,
scrollBarProc, 0L);
/*
Create the TE record used for text display. Use defaults for
display characteristics. Setting window style overhauls
display, so can cancel and update event pending for the window.
*/
CalcEditRect (&r);
dispTE = TENew (&r, &r);
# ifndef singleDisplay
/*
Get new information structure, attach to list of known display
windows.
*/
dInfo = New (DisplayInfo);
(**dInfo).dNext = dwList;
dwList = dInfo;
(**dInfo).dWind = dispWind;
(**dInfo).dScroll = dispScroll;
(**dInfo).dTE = dispTE;
# endif
SetDWindowNotify (dispWind, d_activate);
SetDWindowFlush (dispWind, d_maxText, d_flushAmt);
SetDWindowStyle (dispWind, d_font, d_size, d_wrap, d_just);
/*
Make window current display output window
*/
SetDWindow (dispWind);
SetPort (savePort);
}
/*
Create and initialize a display window and the associated data
structures, and return the window pointer. Install window in
list of display windows. In single-window mode, disallow
creation of a new window if one already exists.
The parameters are similar to those for NewWindow. See Inside
Macintosh.
*/
WindowPtr NewDWindow (bounds, title, visible, behind, goAway, refCon)
Rect *bounds;
StringPtr title;
Boolean visible;
WindowPtr behind;
Boolean goAway;
long refCon;
{
# ifdef singleDisplay
if (dispWind != nil)
return (nil);
# endif
dispWind = NewWindow (nil, bounds, title, visible,
documentProc, behind, goAway, refCon);
SetupDWindow ();
return (dispWind);
}
/*
Create and initialize a display window (using a resource) and
the associated data structures, and return the window pointer.
Install window in list of display windows. In single-window
mode, disallow creation of a new window if one already exists.
The parameters are similar to those for GetNewWindow. See Inside
Macintosh.
*/
WindowPtr GetNewDWindow (resourceNum, behind)
int resourceNum;
WindowPtr behind;
{
# ifdef singleDisplay
if (dispWind != nil)
return (nil);
# endif
dispWind = GetNewWindow (resourceNum, nil, behind);
SetupDWindow ();
return (dispWind);
}
/* ------------------------------------------------------------ */
/* Output Routines */
/* ------------------------------------------------------------ */
/*
Write text to display area if output is on (curDispWind != nil).
DisplayText is the fundamental output routine. All other
output calls map (eventually) to it.
First check whether the insertion will cause overflow and flush
out some stuff if so. Insert new text at the end, then test
whether lines must be scrolled to get the new stuff to show up.
If yes, then do the scroll. Set values of scroll bar properly
and highlight as appropriate.
The current port is preserved. Since all output calls end up
here, it's the only output routine that has to save the port
and check whether output is on.
*/
DisplayText (theText, len)
Ptr theText;
long len;
{
register int nLines; /* number of lines in TERec */
register int dispLines; /* number of lines displayable in window */
register int topLines; /* number of lines currently scrolled off top */
register int scrollLines; /* number of lines to scroll up */
register int lHeight;
Rect r;
GrafPtr savePort;
register TEHandle dTE;
if (curDispWind == nil)
return;
GetPort (&savePort);
SetPort (curDispWind);
SyncGlobals (curDispWind);
dTE = dispTE;
if ((**dTE).teLength + len > dMaxText) /* check overflow */
{
FlushDWindow (dispWind, dFlushAmt);
DisplayString ("\p\r(autoflush occurred)\r");
}
lHeight = (**dTE).lineHeight;
TESetSelect (32767L, 32767L, dTE); /* set to insert at end */
TEInsert (theText, len, dTE);
r = (**dTE).viewRect;
nLines = (**dTE).nLines;
dispLines = (r.bottom - r.top) / lHeight;
topLines = LinesOffTop ();
scrollLines = nLines - (topLines + dispLines);
if (scrollLines > 0) /* must scroll up */
TEScroll (0, -lHeight * scrollLines, dTE); /* scroll up */
topLines = nLines - dispLines;
if (topLines >= 0 && GetCtlMax (dispScroll) != topLines)
{
SetCtlMax (dispScroll, topLines);
SetCtlValue (dispScroll, topLines);
}
HiliteScroll ();
SetPort (savePort);
}
/*
Derived output routines:
DisplayString Write (Pascal) string
DisplayLong Write value of long integer
DisplayInt Write value of integer
DisplayChar Write character
DisplayHexLong Write value of long integer in hex (8 digits)
DisplayHexInt Write value of integer in hex (4 digits)
DisplayHexChar Write value of character in hex (2 digit)
DisplayBoolean Write boolean value
DisplayLn Write carriage return
*/
DisplayString (theStr)
StringPtr theStr;
{
DisplayText (theStr+1, (long) theStr[0]);
}
DisplayLong (l)
long l;
{
Str255 s;
NumToString (l, s);
DisplayString (s);
}
DisplayInt (i)
int i;
{
DisplayLong ((long) i);
}
DisplayChar (c)
char c;
{
DisplayText (&c, 1L);
}
DisplayLn ()
{
DisplayChar ('\r');
}
DisplayBoolean (b)
Boolean b;
{
DisplayString (b ? "\ptrue" : "\pfalse");
}
static HexByte (value) /* should be 0..15 */
int value;
{
DisplayChar ((char) (value + (value < 10 ? '0' : 'a' - 10)));
}
DisplayHexChar (c)
char c;
{
HexByte ((int) (c >> 4) & 0x0f);
HexByte ((int) c & 0x0f);
}
DisplayHexInt (i)
int i;
{
DisplayHexChar ((char) ((i >> 8) & 0xff));
DisplayHexChar ((char) (i & 0xff));
}
DisplayHexLong (l)
long l;
{
DisplayHexInt ((int) (l >> 16) & 0xffff);
DisplayHexInt ((int) l & 0xffff);
}